﻿using MvcApplication1.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {

        [HttpPost]
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Index(DailyUpdatesModel model)
        {
            StorageService.StorageServiceClient client = new StorageService.StorageServiceClient();
            List<StorageService.Report> reports = client.GetReports().ToList();

            reports = reports.OrderBy(x => x.Modified.DateTime).ToList();
            reports.Reverse();
            model.reports = reports;

            ViewBag.Username = FindUsername();
            
            return View(model);
        }

        public ActionResult ViewReport(ViewReportModel model, string name)
        {
            StorageService.StorageServiceClient client = new StorageService.StorageServiceClient();
            string report = client.GetReport(name);

            /*string filePath2 = Server.MapPath(Url.Content("~/Data/json.txt"));
            FileStream stream = new FileStream(filePath2, FileMode.Create, FileAccess.Write);
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.WriteLine(report);
            }*/

            model.report = report;
            model.VIN = FindVIN(report);

            /*JToken token = JObject.Parse(report);
            model.ExcessiveAccelerationCount = (int)token.SelectToken("ExcessiveAccelerationCount");
            model.SuddenBrakingCount = (int)token.SelectToken("SuddenBrakingCount");
            model.HardTurnCount = (int)token.SelectToken("HardTurningCount");
            model.SpeedingCount = (int)token.SelectToken("SpeedingCount");
            model.ExcessiveAccelerationTotal = Math.Round((double)token.SelectToken("ExcessiveAccelerationDeductions"), 2, MidpointRounding.AwayFromZero);
            model.SuddenBrakingTotal = Math.Round((double)token.SelectToken("SuddenBrakingDeductions"), 2, MidpointRounding.AwayFromZero);
            model.HardTurnTotal = Math.Round((double)token.SelectToken("HardTurningDeductions"), 2, MidpointRounding.AwayFromZero);
            model.SpeedingTotal = Math.Round((double)token.SelectToken("SpeedingDeductions"), 2, MidpointRounding.AwayFromZero);*/

            model.jObject = Newtonsoft.Json.Linq.JObject.Parse(report);
            model.ExcessiveAccelerationCount = (int)model.jObject["ExcessiveAccelerationCount"];
            model.SuddenBrakingCount = (int)model.jObject["SuddenBrakingCount"];
            model.HardTurnCount = (int)model.jObject["HardTurningCount"];
            model.SpeedingCount = (int)model.jObject["SpeedingCount"];
            model.ExcessiveAccelerationTotal = Math.Round((double)model.jObject["ExcessiveAccelerationDeductions"], 2, MidpointRounding.AwayFromZero);
            model.SuddenBrakingTotal = Math.Round((double)model.jObject["SuddenBrakingDeductions"], 2, MidpointRounding.AwayFromZero);
            model.HardTurnTotal = Math.Round((double)model.jObject["HardTurningDeductions"], 2, MidpointRounding.AwayFromZero);
            model.SpeedingTotal = Math.Round((double)model.jObject["SpeedingDeductions"], 2, MidpointRounding.AwayFromZero);

            model.snapshots = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Snapshot>>(model.jObject["Snapshots"].ToString());

            ViewBag.Username = FindUsername();

            return View(model);
        }

        public ActionResult FindReports(FindReportsModel model)
        {
            ViewBag.Username = FindUsername();

            model.driverArray = FindDrivers(ViewBag.Username);
            model.VINArray = FindVINsComplete();

            return View(model);
        }

        public ActionResult ChooseReports(ChooseReportsModel model)
        {
            ViewBag.Username = FindUsername();

            StorageService.StorageServiceClient client = new StorageService.StorageServiceClient();
            List<StorageService.Report> reports = client.GetReports().ToList();

            model.reports = reports;

            for (int i = 0; i < reports.Count(); i++)
            {
                StorageService.Report currentReport = reports[i];

                // Check if the report is within the date range.
                if (model.Date1 != null)
                {
                    DateTime date1 = DateTime.Parse(model.Date1);
                    DateTime reportDate = DateTime.Parse(currentReport.Modified.DateTime.ToString());
                    if (model.Date2 != null)
                    {
                        DateTime date2 = DateTime.Parse(model.Date2);
                        // Add a day and subtract one second from date2 to ensure that the entire calendar day is included.
                        date2.AddDays(1);
                        date2.AddSeconds(-1);

                        if (!(reportDate >= date1 && reportDate <= date2))
                        {
                            reports.RemoveAt(i);
                            i--;
                            continue;
                        }
                    }
                    else
                    {
                        if (!(reportDate >= date1 && reportDate < date1.AddDays(1)))
                        {
                            reports.RemoveAt(i);
                            i--;
                            continue;
                        }
                    }
                }

                // Check if report has the correct VIN.
                if (model.VIN != "None")
                {
                    if (currentReport.VIN != model.VIN)
                    {
                        reports.RemoveAt(i);
                        i--;
                        continue;
                    }
                }

                // Check if report has the correct driver.
                if (model.Driver != "None")
                {
                    if (model.ParseVIN(currentReport, ViewBag.Username) != model.Driver)
                    {
                        reports.RemoveAt(i);
                        i--;
                        continue;
                    }
                }

                // Check if report has the correct grade.
                if (model.Grade != "None")
                {
                    if (currentReport.Grade != model.Grade)
                    {
                        reports.RemoveAt(i);
                        i--;
                        continue;
                    }
                }

                // Check if report has the correct infractions.
                if (model.Infraction1 != null || model.Infraction2 != null || model.Infraction3 != null || model.Infraction4 != null)
                {
                    int code = currentReport.Infractions;
                    if (model.Infraction4 != null)
                    {
                        if (!(code / 8 > 0))
                        {
                            reports.RemoveAt(i);
                            i--;
                            continue;
                        }
                    }
                    code %= 8;
                    if (model.Infraction3 != null)
                    {
                        if (!(code / 4 > 0))
                        {
                            reports.RemoveAt(i);
                            i--;
                            continue;
                        }
                    }
                    code %= 4;
                    if (model.Infraction2 != null)
                    {
                        if (!(code / 2 > 0))
                        {
                            reports.RemoveAt(i);
                            i--;
                            continue;
                        }
                    }
                    code %= 2;
                    if (model.Infraction1 != null)
                    {
                        if (code != 1)
                        {
                            reports.RemoveAt(i);
                            i--;
                            continue;
                        }
                    }
                }
            }

            return View(model);
        }

        public ActionResult ReportLadder(ReportLadderModel model)
        {
            ViewBag.Username = FindUsername();

            StorageService.StorageServiceClient client = new StorageService.StorageServiceClient();
            List<StorageService.Report> reports = client.GetReports().ToList();
            reports = reports.OrderBy(x => x.Modified.DateTime).ToList();

            model.reports = reports;

            model.years = model.GetYears();
            model.months = model.GetMonths();
            model.days = model.GetDays();

            return View(model);
        }

        public ActionResult Settings(SettingsModel model)
        {
            ViewBag.Username = FindUsername();
            ViewBag.Message = "Adjust IntelliFleet to fit your personal preferences.";

            model.VINs = FindVINsComplete();

            return View(model);
        }

        [HttpPost]
        public ActionResult Settings(SettingsModel model, string status)
        {
            ViewBag.Username = FindUsername();
            ViewBag.Message = "Your settings have been changed.";

            UpdateDriverName(model.VIN, model.Driver, ViewBag.Username);

            return View(model);
        }

        public ActionResult About()
        {
            ViewBag.Username = FindUsername();

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Username = FindUsername();

            return View();
        }

        /// <summary>
        /// Finds the VIN in a string JSON report.
        /// </summary>
        /// <param name="rep">JSON report in string format.</param>
        /// <returns>VIN associated with the report.</returns>
        private string FindVIN(string rep)
        {
            int index = rep.IndexOf("VIN");
            if (index != -1)
            {
                return rep.Substring(index + 6, 17);
            }
            return "";
        }

        /// <summary>
        /// Finds all VINs associated with a particular account that have been assigned a driver.
        /// </summary>
        /// <param name="username">Username currently in session.</param>
        /// <returns>List of all VINs associated with account.</returns>
        private List<string> FindVINs(string username)
        {
            string line = "";
            List<string> vins = new List<string>();
            string filePath = Server.MapPath(Url.Content("~/Data/drivernames.txt"));
            using (StreamReader reader = new StreamReader(filePath))
            {
                while (!reader.EndOfStream)
                {
                    line = reader.ReadLine();
                    if (username == line)
                    {
                        while (!reader.EndOfStream)
                        {
                            line = reader.ReadLine();
                            if (!line.Contains("@"))
                            {
                                vins.Add(line);
                                line = reader.ReadLine();
                            }
                            else
                            {
                                break;
                            }
                        }
                        break;
                    }
                }
            }
            return vins;
        }

        /// <summary>
        /// Finds all VINs associated with a particular account.
        /// </summary>
        /// <param name="username">Username currently in session.</param>
        /// <returns>List of all VINs associated with account.</returns>
        private List<string> FindVINsComplete()
        {
            List<string> vins = new List<string>();

            StorageService.StorageServiceClient client = new StorageService.StorageServiceClient();
            List<StorageService.Report> reports = client.GetReports().ToList();

            foreach (StorageService.Report report in reports)
            {
                vins.Add(report.VIN);
            }
            vins = vins.Distinct().ToList();
            
            return vins;
        }

        /// <summary>
        /// Finds all drivers associated with a particular account.
        /// </summary>
        /// <param name="username">Username currently in session.</param>
        /// <returns>List of all drivers associated with account.</returns>
        private List<string> FindDrivers(string username)
        {
            string line = "";
            List<string> drivers = new List<string>();
            string filePath = Server.MapPath(Url.Content("~/Data/drivernames.txt"));
            using (StreamReader reader = new StreamReader(filePath))
            {
                while (!reader.EndOfStream)
                {
                    line = reader.ReadLine();
                    if (username == line)
                    {
                        while (!reader.EndOfStream)
                        {
                            line = reader.ReadLine();
                            if (!line.Contains("@"))
                            {
                                line = reader.ReadLine();
                                if (!drivers.Contains(line))
                                {
                                    drivers.Add(line);
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        break;
                    }
                }
            }
            return drivers;
        }

        /// Finds all drivers associated with a particular account, including repeated instances.
        /// </summary>
        /// <param name="username">Username currently in session.</param>
        /// <returns>List of all drivers associated with account.</returns>
        private List<string> FindDriversRepeats(string username)
        {
            string line = "";
            List<string> drivers = new List<string>();
            string filePath = Server.MapPath(Url.Content("~/Data/drivernames.txt"));
            using (StreamReader reader = new StreamReader(filePath))
            {
                while (!reader.EndOfStream)
                {
                    line = reader.ReadLine();
                    if (username == line)
                    {
                        while (!reader.EndOfStream)
                        {
                            line = reader.ReadLine();
                            if (!line.Contains("@"))
                            {
                                line = reader.ReadLine();
                                drivers.Add(line);
                            }
                            else
                            {
                                break;
                            }
                        }
                        break;
                    }
                }
            }
            return drivers;
        }

        public void UpdateDriverName(string vin, string driver, string username)
        {
            List<string> VINsInSystem = FindVINs(username);
            StringBuilder final = new StringBuilder();
            bool written = false;
            if (VINsInSystem.Contains(vin))
            {
                string line = "";
                string filePath = Server.MapPath(Url.Content("~/Data/drivernames.txt"));
                using (StreamReader reader = new StreamReader(filePath))
                {
                    line = reader.ReadLine();
                    while (!reader.EndOfStream)
                    {
                        if (line == vin)
                        {
                            final.AppendLine(line);
                            line = reader.ReadLine();
                            final.AppendLine(driver);
                        }
                        else
                        {
                            final.AppendLine(line);
                        }
                        line = reader.ReadLine();
                    }
                }
            }
            else
            {
                string line = "";
                string filePath = Server.MapPath(Url.Content("~/Data/drivernames.txt"));
                using (StreamReader reader = new StreamReader(filePath))
                {
                    line = reader.ReadLine();
                    while (!reader.EndOfStream)
                    {
                        final.AppendLine(line);
                        if (line == username)
                        {
                            line = reader.ReadLine();
                            while (!reader.EndOfStream)
                            {
                                if (line.Contains("@") && !written)
                                {
                                    final.AppendLine(vin);
                                    final.AppendLine(driver);
                                    final.AppendLine(line);
                                    written = true;
                                }
                                else
                                {
                                    final.AppendLine(line);
                                }
                                line = reader.ReadLine();
                            }
                            final.AppendLine(line);
                            if (!written)
                            {
                                final.AppendLine(vin);
                                final.AppendLine(driver);
                            }
                        }
                    }
                }
            }

            string filePath2 = Server.MapPath(Url.Content("~/Data/drivernames.txt"));
            FileStream stream = new FileStream(filePath2, FileMode.Create, FileAccess.Write);
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(final);
            }
        }

        public string FindUsername()
        {
            // Find the username to populate the text box at the top of each page.
            string line = "";
            string filePath = Server.MapPath(Url.Content("~/Data/sessiondata.txt"));
            using (StreamReader reader = new StreamReader(filePath))
            {
                line = reader.ReadLine();
            }
            return line;
        }
    }
}
